package cc.vv.party.service.impl;

import cc.vv.party.beans.model.Project;
import cc.vv.party.beans.model.ProjectApply
import cc.vv.party.beans.model.ProjectSegmentation
import cc.vv.party.beans.vo.*
import cc.vv.party.mapper.ProjectMapper;
import cc.vv.party.service.ProjectService;
import cc.vv.party.common.base.BaseServiceImpl;
import cc.vv.party.common.constants.StatusCode
import cc.vv.party.common.ext.uuid
import cc.vv.party.common.ext.wrapper
import cc.vv.party.common.wrapper.PageWrapper
import cc.vv.party.exception.BizException
import cc.vv.party.mapper.ProjectApplyMapper
import cc.vv.party.mapper.ProjectSegmentationMapper
import cc.vv.party.param.ProjectListParam
import cc.vv.party.param.ProjectSaveParam
import cc.vv.party.param.ProjectStatisticsParam
import cn.hutool.core.date.DateUtil
import com.baomidou.mybatisplus.mapper.EntityWrapper
import com.baomidou.mybatisplus.plugins.Page
import commonx.core.content.transfer
import commonx.core.content.transferEntries
import org.apache.commons.collections.CollectionUtils
import org.apache.commons.lang.StringUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
import kotlin.collections.HashSet
import kotlin.streams.toList

/**
 * <p>
 * 项目信息 服务实现类
 * </p>
 *
 * @author Gyb
 * @since 2018-10-12
 */
@Service
open class ProjectServiceImpl : BaseServiceImpl<ProjectMapper, Project>(), ProjectService {

    @Autowired
    lateinit var projectSegmentationMapper: ProjectSegmentationMapper

    @Autowired
    lateinit var projectApplyMapper: ProjectApplyMapper

    @Transactional(rollbackFor = [(Exception::class)])
    override fun edit(param: ProjectSaveParam, user: UserVO, userId: String): Boolean {
        var entity: Project?

        //今天的时间
        val endOfDayTime = DateUtil.endOfDay(Date()).time
        //判断项目的预警时间是不是在今天及今天之前
        var isWaring = endOfDayTime <= DateUtil.endOfDay(DateUtil.date(param.warningTime!!)).time
        if(StringUtils.isBlank(param.id)){
            entity = param.transfer<Project>()
            entity.id = uuid()
            entity.applyType = Integer(1)
            entity.street = user.street
            entity.community = user.community
            entity.grid = user.grid
            entity.createUser = userId
            if(param.startTime != null) entity.startTime = Date(param.startTime!!)
            if(param.endTime != null) entity.endTime = Date(param.endTime!!)

            if(CollectionUtils.isNotEmpty(param.segmentationList) ){
                for (child in param.segmentationList!!){
                    child.id = uuid()
                    child.projectId = entity.id
                    child.transfer<ProjectSegmentation>().insert()

                    //判断项目的预警时间是不是在今天及今天之前
                    if(child.warningTime != null && endOfDayTime <= DateUtil.endOfDay(DateUtil.date(child.warningTime!!)).time){
                        isWaring = true
                    }
                }
            }

            if(isWaring){
                entity.sysState = Integer(2)
            }
            super.insert(entity)
        } else {
            entity = super.selectById(param.id) ?: throw BizException(StatusCode.MESSAGE_NOT_EXIST)
            if(StringUtils.isNotBlank(param.projectName)) entity.projectName = param.projectName
            if(StringUtils.isNotBlank(param.projectIntroduction)) entity.projectIntroduction = param.projectIntroduction
            if(StringUtils.isNotBlank(param.projectType)) entity.projectType = param.projectType
            if(param.startTime != null) entity.startTime = Date(param.startTime!!)
            if(param.endTime != null) entity.endTime = Date(param.endTime!!)
            if(StringUtils.isNotBlank(param.principal)) entity.principal = param.principal
            if(StringUtils.isNotBlank(param.mobile)) entity.mobile = param.mobile
            if(param.declarationTime != null ) entity.declarationTime = Date(param.declarationTime!!)
            if(param.warningTime != null ) entity.warningTime = Date(param.warningTime!!)
            if(param.completeTime != null ) entity.completeTime = Date(param.completeTime!!)
            if(param.state != null ) entity.state = param.state
            if(StringUtils.isNotBlank(param.street)) entity.street = param.street
            if(StringUtils.isNotBlank(param.community)) entity.community = param.community
            if(StringUtils.isNotBlank(param.grid)) entity.grid = param.grid
            if(StringUtils.isNotBlank(param.checkReson)) entity.checkReson = param.checkReson
            if(StringUtils.isNotBlank(param.visibleRange)) entity.visibleRange = param.visibleRange

            entity.applyType = Integer(0)

            var wrapper = EntityWrapper<ProjectSegmentation>().where("project_id = {0}", entity.id)
            val list = projectSegmentationMapper.selectList(wrapper)
            var map = HashMap<String, ProjectSegmentation>()
            var exitIdSet = HashSet<String>()
            if(CollectionUtils.isNotEmpty(list)){
                for(temp in list){
                    exitIdSet.add(temp.id!!)
                    map[temp.id!!] = temp
                }
            }

            if(CollectionUtils.isNotEmpty(param.segmentationList)){
                //排除更新数据
                for(temp in param.segmentationList!!){
                    exitIdSet.remove(temp.id)

                    //更新数据
                    if(map.containsKey(temp.id) && map[temp.id] != null){
                        var child = map[temp.id]
                        child!!.stage = temp.stage
                        child!!.content = temp.content
                        child!!.warningTime = Date(temp.warningTime!!)
                        child!!.completeTime = Date(temp.completeTime!!)
                        child!!.state = temp.state
                        child.insertOrUpdate()

                        //判断项目的预警时间是不是在今天及今天之前
                        if(endOfDayTime <= DateUtil.endOfDay(DateUtil.date(child.warningTime!!)).time){
                            isWaring = true
                        }
                    }
                }

                //删除已经删除的数据
                if(CollectionUtils.isNotEmpty(exitIdSet) && exitIdSet.size > 0){
                    projectSegmentationMapper.deleteBatchIds(exitIdSet)
                }

            } else {
                projectSegmentationMapper.delete(wrapper)
            }

            if(isWaring){
                entity.sysState = Integer(2)
            }

            entity.updateById()
        }
        return true
    }

    @Transactional(rollbackFor = [(Exception::class)])
    override fun deleteProject(id: String): Boolean {
        var wrapper = EntityWrapper<ProjectSegmentation>()
        wrapper.where("project_id = {0}", id)
        projectSegmentationMapper.delete(wrapper)

        super.deleteById(id)
        return true
    }


    override fun info(id: String): ProjectVO {
        var entity = super.selectById(id) ?: throw BizException(StatusCode.MESSAGE_NOT_EXIST.statusCode, "项目信息不存在")
        if(entity.view != null && entity.view!!.toInt() == 1){
            entity.view = Integer(2)
            entity.updateById()
        }

        var wrapper = EntityWrapper<ProjectSegmentation>()
        wrapper.where("project_id = {0}", entity.id).orderBy("stage", true)
        var child = projectSegmentationMapper.selectList(wrapper)

        var result = entity.transfer<ProjectVO>()
        if(CollectionUtils.isNotEmpty(child)){
            result.segmentationList = child.transferEntries<ProjectSegmentationVO>() as ArrayList
        }

        var applyList = projectApplyMapper.selectList(EntityWrapper<ProjectApply>().where("pro_id = {0}", entity.id))
        if(CollectionUtils.isNotEmpty(applyList)){
            var segmMap = HashMap<String, ArrayList<ProjectApplyVO>>()
            for(temp in applyList){
                if(temp.type!!.toInt() == 0){
                   result.applyInfo  = temp.transfer()
                } else {
                    var list: ArrayList<ProjectApplyVO>
                    if(segmMap.containsKey(temp.segId)){
                        list = segmMap[temp.segId!!] as ArrayList<ProjectApplyVO>
                        list.add(temp.transfer())
                    } else {
                        list = ArrayList()
                        list.add(temp.transfer())
                    }
                    segmMap[temp.segId!!] = list
                }
            }

            for(temp in result.segmentationList!!){
                temp.applyList = segmMap[temp.id!!]
            }
        }
        return result
    }

    override fun appListPage(street: String?, community: String?, grid: String?, title: String?, state: String?, size: Int, page: Int, user: UserVO): PageWrapper<ProjectVO> {
        var p = Page<ProjectVO>(page, size)
        p.records = baseMapper.findAppListPage(p, street, community, grid, title, state, user)
        return p.transfer()
    }

    override fun pcListPage(size: Int, page: Int, type: Int): PageWrapper<ProjectVO> {
        var wrapper = EntityWrapper<Project>()
        wrapper.and("visible_range = '4' ")
        wrapper.and("check_state = 0 ")
        wrapper.orderBy("create_time", false)
        var pages = super.selectPage(Page(page, size), wrapper)
        return pages.wrapper()
    }

    override fun listPage(param: ProjectListParam, size: Int, page: Int, type: Int): PageWrapper<ProjectVO> {
        var wrapper = EntityWrapper<Project>()
        if(StringUtils.isNotBlank(param.projectName)) wrapper.and("project_name = {0}", param.projectName)
        if(StringUtils.isNotBlank(param.projectType)) wrapper.and("project_type = {0}", param.projectType)
        if(StringUtils.isNotBlank(param.principal)) wrapper.and("principal = {0}", param.principal)
        if(StringUtils.isNotBlank(param.mobile)) wrapper.and("mobile = {0}", param.mobile)
        if(param.state != null) wrapper.and("sys_state = {0}", param.state)
        if(StringUtils.isNotBlank(param.street)) wrapper.and("street = {0}", param.street)
        if(StringUtils.isNotBlank(param.community)) wrapper.and("community = {0}", param.community)
        if(StringUtils.isNotBlank(param.grid)) wrapper.and("grid = {0}", param.grid)
        if(0 == type){
            wrapper.and("check_state is null ")
        }
        wrapper.orderBy("create_time", false)
        var pages = super.selectPage(Page(page, size), wrapper)
        return pages.wrapper()
    }

    override fun findWarnListPage(param: ProjectListParam, size: Int, page: Int): PageWrapper<ProjectVO> {
        var wrapper = EntityWrapper<Project>()
        if(StringUtils.isNotBlank(param.projectName)) wrapper.and("project_name = {0}", param.projectName)
        if(StringUtils.isNotBlank(param.projectType)) wrapper.and("project_type = {0}", param.projectType)
        if(StringUtils.isNotBlank(param.principal)) wrapper.and("principal = {0}", param.principal)
        if(StringUtils.isNotBlank(param.mobile)) wrapper.and("mobile = {0}", param.mobile)
        if(param.state != null) wrapper.and("state = {0}", param.state)
        if(StringUtils.isNotBlank(param.street)) wrapper.and("street = {0}", param.street)
        if(StringUtils.isNotBlank(param.community)) wrapper.and("community = {0}", param.community)
        if(StringUtils.isNotBlank(param.grid)) wrapper.and("grid = {0}", param.grid)
        wrapper.and("sys_state = 2") //查看预警项目
        wrapper.orderBy("create_time", false)
        var pages = super.selectPage(Page(page, size), wrapper)
        return pages.wrapper()
    }

    override fun projectSysStateStatistics(param: ProjectStatisticsParam): Map<String, Integer> {
        var list = baseMapper.selectProjectSysStateStatistics(param)
        var map = HashMap<String, Integer>()
        if(CollectionUtils.isNotEmpty(list)){
            for(temp in list){
                map[temp["state"].toString()] = Integer(temp["num"].toString())
            }
        }
        return map
    }

    override fun updateProjectApply(id: String, type: Int, applyReson: String, sysState: Int) {
        baseMapper.updateProjectApply(id, type, applyReson, sysState)
    }

}
